using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics.Contracts;

namespace Granite.Data
{
	/// <summary>
	/// A light-weight object to hold tabular data
	/// </summary>
	/// <remarks>This is much faster than a DataTable, but lacks most of its features.</remarks>
	[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")]
	public class Table : Collection<Dictionary<string, object>>
	{
		readonly List<string> m_Columns;
		readonly Dictionary<string, Type> m_ColumnTypes;

		/// <summary>
		/// Creates a new Table from an IDataReader
		/// </summary>
		/// <param name="source"></param>
		public Table(IDataReader source)
		{
			if (source == null)
				throw new ArgumentNullException("source", "source is null.");
			if (source.FieldCount == 0)
				throw new DataException("No columns were returned");
			Contract.EndContractBlock();

			m_Columns = new List<string>(source.FieldCount);
			m_ColumnTypes = new Dictionary<string, Type>(source.FieldCount, StringComparer.OrdinalIgnoreCase);
			for (var i = 0; i < source.FieldCount; i++)
			{
				m_Columns.Add(source.GetName(i));
				m_ColumnTypes.Add(source.GetName(i), source.GetFieldType(i));
			}

			while (source.Read())
			{
				var row = new Dictionary<string, object>();
				for (var i = 0; i < source.FieldCount; i++)
				{
					var temp = source[i];
					if (temp==DBNull.Value)
						temp=null;

					row.Add(m_Columns[i], temp);
				}

				Add(row);
			}
		}

		/// <summary>
		/// List of columns and their types.
		/// </summary>
		public Dictionary<string, Type> Columns
		{
			get { return m_ColumnTypes; }
		}
	}
}
